# -*- coding: utf-8 -*- 

import socket, sys, threading,time
import wx 
from pyDemin import * 
from pyD import *
host = '127.0.0.1' 
port = int(sys.argv[1])#80037
conf=[]
maxj=1  #nombre max de joueurs , nb necessaire pour debuter la partie
conn_client={} #dictionnaire des connexions clients 
dico={}
lesgrilles={} # dictionnaires des grilles joueurs
ferme=0
verrou=threading.Lock()
### definir une class threadclient  
#class threadclient: 





class threadconnexion(threading.Thread) :  
 
#creation de la socket puis connexion 
    def __init__(self,conn) : #conn reference de con 
        threading.Thread.__init__(self) 
        self.connexion=conn 
#        ferme=0 #connexion ouverte si 0 , ou renvoie en break si 1 (ferme la connexion)
        #confirm=0#lorsque confirm atteint 3, tous les joueurs on repondu le '0'=> ok 
        
 
#actions du serveur en reponse au client  
    def run(self):
        nom=self.getName()
        grillechar=''#grille sous forme de caractere, pour la send par socket
        verrou.acquire()
        if len(conn_client)<maxj:
            conn_client[nom]=self.connexion
        verrou.release()
    #        conn_client[nom].send("que voulez-vous faire ?")
        while 1:
           # conn_client[nom].send("que voulez-vous faire ?")
            msg = self.connexion.recv(1024) #recoit du client 
            msg=msg.split(',')
            print "**%s** > %s" % (nom,msg[0]) 
            if msg[0]=='FIN' or msg[0].upper()=="FIN" or msg[0]=="" :#bouton close
                self.findeconnexion(nom)
                break
            elif msg[0]=='0': #'clientOK':
                if ferme<>1:
                    conf.append(nom+'ok')
                    self.clientOK(nom)
#                if ferme==1:
#                    break

# confirmation des clients:
                
            elif msg[0]=="OK":                
                self.OK(msg,nom)
                         
# Requête d'envoi du nb de joueurs:
            elif msg[0]=="nbj":
                print "nbj ok demanded"
               # print conn_client
                for cli in conn_client:#on envoie l'info à tout le monde !
                    conn_client[cli].send("nbj."+str(len(conn_client))+"."+str(maxj))
                  #  time.sleep(2)
       
# cas du clic gauche d'un client:
            elif msg[0]=="L":
                self.clientclikG(msg,nom)
                #on renvoit la grille modifiee au client. La modification a aussi ete enregistree ds notre dictionnaire

# cas du clic droit d'un client
            elif msg[0]=='R':
                self.clientclikD(msg,nom)
                #on renvoit la grille modifiee au client. La modification a aussi ete enregistree ds notre dictionnaire

        self.connexion.close() 
   #     print conn_client
   #     print "**"+nom+"**"
   #     del conn_client[nom]
  #      print "client %s deconnecte "% nom + 'il reste %d joueurs'% len(conn_client)



    def findeconnexion(self,nom):
        verrou.acquire()
        del conn_client[nom]#ooo pk dans la boucle for
	for cli in conn_client:
            conn_client[cli].send("M, " + "%s"%(nom)+" a quitte la partie")
        print "client %s deconnecte "% nom + 'il reste %d joueurs'% len(conn_client)
        verrou.release()
        return 0
    
      



    def clientOK(self,nom):
        verrou.acquire()
        if len(conn_client)>maxj : #deuxieme verif
            #break ooo
            #del conn_client[nom]
            ferme=1
        elif len(conn_client)<maxj:
            for cli in conn_client:
                conn_client[cli].send("M, " + "il y a "+ "%d"%len(conn_client)+" joueurs, patientez") 
            for cli in conn_client:
                if cli != nom: # ne pas le renvoyer a l'emetteur
                    conn_client[cli].send("M, "+"%s"%(nom)+'a rejoint la parti')
            self.connexion.send("il y a"+"%d"%len(conn_client)+"joueurs, patientez") 
        elif len(conn_client)==maxj:
            print("%d"%len(conf))
#lorsque le nb de joueurs est ok pr commencer une partie , creation de la grille, envoie des parametres+grille
            for cli in conn_client:
                if cli != nom: # ne pas le renvoyer a l'emetteur
                    conn_client[cli].send("M, " +"%s"%(nom)+'a rejoint la partie')
                if len(conf)==maxj:
                    conn_client[cli].send("M, "+"Begin party ?")
        verrou.release()

    def OK(self,msg,nom):
        print("inOK")
        verrou.acquire()
        if len(conn_client)==maxj:
            dico[nom]=msg
            print ("%d"%len(dico))
            if len(dico)==len(conn_client):
                l=20
                L=20
                nm=150
              #  Demi=pyDemin(l,L,nm)#creation de l'objet demineur, et donc de la grille
               # Demi.comptemine()
               # grillechar=''
                #for i in range(len(Demi.y)):
                #    grillechar=grillechar+",%d"%Demi.y[i]	
                #    print grillechar
                conn_clientsave=conn_client.copy()
                for cli in conn_clientsave:
                    conn_client[cli].send('G,'+'%d , %d, %d '%(l,L,nm))#+grillechar)
                    #time.sleep(2)
                    #                    self.connexion.send('l,L,'+grillechar)
                    
                    print("grille envoyee")
# il faut sauvegarder une grille pour chaque joueur pour suivre leurs avancees
#on cree un dico de grille
                for cli in conn_client:
                    lesgrilles[cli]=pyDemin(l,L,nm)
#                    lesgrilles[cli].inf=Demi.inf.copy()#pour copier un numpy le [:] ne fonctionne pas, mais il existe une methode prevue pour
#                    lesgrilles[cli].deco=Demi.deco.copy()
# pour chaque client, on fait attention a copier un objet et pas un pointeur
        verrou.release()

    def clientclikG(self,msg,nom):
        x,y=[msg[1],msg[2]]
        verrou.acquire()
        if lesgrilles[nom].encours==0:
            k=0
            if lesgrilles[nom].deco[int(x),int(y)]!=2:
                a=lesgrilles[nom].devoil(int(x),int(y))
                lesgrilles[nom].recursion(int(x),int(y))
                if a!=-1:#si c toujours bon (?)
                    grillechar=''
                    for i in range(lesgrilles[nom].l):
                        for j in range(lesgrilles[nom].L):
# on reforme la grille a envoyer au client avec
                            if lesgrilles[nom].deco[i,j]==1:  
                                grillechar=grillechar + ",%d"%lesgrilles[nom].inf[i,j] #le nb de mines voisines
                            elif lesgrilles[nom].deco[i,j]==2 :
                                grillechar=grillechar + ",-2"  # -2 si la case est deja drapeautee
                            else:
                                grillechar=grillechar + ",-1"   # -1 si la case n'est pas encore decouverte
                                                     
                    conn_client[nom].send('Gupdate'+grillechar)#on envoie au client la nouvelle grille 
                    
                    #self.init_buffer()
                else:
                    lesgrilles[nom].encours=1
                    conn_client[nom].send(",PERDU")
            else : 
                conn_client[nom].send(",Case drapeaute")
            for i in range(lesgrilles[nom].l):
                for j in range(lesgrilles[nom].L):
                    if lesgrilles[nom].deco[i,j]==1:
                        k+=1
            if k==(lesgrilles[nom].l*lesgrilles[nom].L-lesgrilles[nom].nm):
                lesgrilles[nom].encours=1
                conn_client[nom].send(",GAGNE")
        verrou.release()

    def clientclikD(self,msg,nom):  #on modifie le deco pour drapeaute ou dedrapeaute la case clike et on envoie la grille update
        x,y=[msg[1],msg[2]]
        verrou.acquire()
        if lesgrilles[nom].deco[int(x),int(y)]==0:
            lesgrilles[nom].deco[int(x),int(y)]=2
        elif lesgrilles[nom].deco[int(x),int(y)]==2:
            lesgrilles[nom].deco[int(x),int(y)]=0

        grillechar=''

        for i in range(lesgrilles[nom].l):
            for j in range(lesgrilles[nom].L):
# on reforme la grille a envoyer au client avec
                if lesgrilles[nom].deco[i,j]==1: 
                    grillechar=grillechar + ",%d"%lesgrilles[nom].inf[i,j] #le nb de mines voisines
                elif lesgrilles[nom].deco[i,j]==2 :
                    grillechar=grillechar + ",-2"  # -2 si la case est deja drapeautee
                else:
                    grillechar=grillechar + ",-1"   # -1 si la case n'est pas encore decouverte
                                                     
        conn_client[nom].send('Gupdate'+grillechar)#on envoie au client la nouvelle grille 
        verrou.release()            






# Initialisation du serveur - Mise en place du socket :



mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    mySocket.bind((host,port))
except socket.error:
    print "La liaison du socket a l'adresse choisie a echoue."
    sys.exit()
print "Serveur pret, en attente de requetes ..."
mySocket.listen(5)

while 1:
    connexion, adresse = mySocket.accept()
# Creer un nouvel objet thread pour gerer la connexion :
    th = threadconnexion(connexion)
    th.start()
    it = th.getName() # identifiant du thread
    verrou.acquire()
    conn_client[it] = connexion
    verrou.release()


#app = GameApp() 
#app.MainLoop()
